package apii.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import apii.server.ServerThings;

/**
 * 
 * @author evgeniy
 *
 */
public class ServletUtils {

	// codes
	public static final int BAD_DISCIPLINE_URL_ELEMENT = -1;
	public static final int BAD_LAB_URL_ELEMENT = -1;
	public static final int BAD_CODE_URL_ELEMENT = -1;
	public static final int BAD_GROUP_URL_ELEMENT = -1;
	public static final int BAD_STUD_URL_ELEMENT = -1;
	
	// url parts
	public static final String PREFIX = "/APII";
	
	// argument names
	public static final String LOGIN_NAME = "apii_login";
	public static final String PASSWORD_NAME = "apii_password";
	public static final String ZIP_ARCHIVE = "zip_archive";

	public static final void createStudHeader(PrintWriter pw, int id,
			String studName, String studGroup) {

		// home, all labs, alert labs
		pw.println("<hr>");
		pw.println("<table id=\"headertext\">");
		pw.println("<tr>");
		pw.println("<td align =\"center\" style=\" width:50%; \">");
		pw.print("<a href=\"" + ServletUtils.PREFIX + "/stud"
				+ "\">Home</a> | ");
		pw.print("<a href=\"" + ServletUtils.PREFIX + "/stud/all_disciplines"
				+ "\">Все предметы</a> | ");
		pw.print("<a href=\"" + ServletUtils.PREFIX + "/stud/active_alerts"
				+ "\">Активные предупреждения</a> | ");
		pw.print("<a href=\"" + ServletUtils.PREFIX + "/stud/all_alerts"
				+ "\">Все предупреждения</a>");
		pw.println("</td>");

		pw.println("<td align=\"right\" style=\" width:50%; \">");
		pw.println("[" + id + "] " + studName + " | " + studGroup
				+ " | <a href=\"" + ServletUtils.PREFIX + "/logout"
				+ "\">Log out</a>");
		pw.println("</td>");
		pw.println("</tr>");
		pw.println("</table>");
		pw.println("<hr>");
	}

	public static final void createStudStyle(PrintWriter pw) {
		pw.println("<style>");
		pw.println("#headertext {" + "color: black;"
				+ "background-color:#8DB8B6;" + "width: 100%;" + "}");
		pw.println("</style>");
	}

	public static final void startCommonStudDoc(PrintWriter pw,
			UserRequesterData urd, String title) {
		String studentName = urd.surname + " " + urd.name + " "
				+ urd.patronimic;
		String studentGroup = urd.groupName;
		pw.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">");

		pw.println("<html>");
		pw.println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">");
		pw.println("<title>" + title + "</title>");
		pw.println("<head>");
		ServletUtils.createStudStyle(pw);
		pw.println("</head>");
		pw.println("<body>");
		ServletUtils.createStudHeader(pw, urd.userId, studentName,
				studentGroup);
	}

	public static final void closeCommonStudDoc(PrintWriter pw,
			UserRequesterData urd) {
		pw.println("</body>");
		pw.println("</html>");
	}

	public static final boolean validateIdentifier(String s) {
		for (int i = 0; i < s.length(); i++) {
			if (!Character.isLetterOrDigit(s.charAt(i))) {
				return false;
			}
		}
		return true;
	}

	public static final boolean validateNumber(String s) {
		for (int i = 0; i < s.length(); i++) {
			if (!Character.isDigit(s.charAt(i))) {
				return false;
			}
		}
		return true;
	}

	public static final void logout(String sessionId) throws SQLException {
		Connection c = ServerThings.getThings().getConnection();
		Statement s = c.createStatement();
		s.executeUpdate("UPDATE apii.user_session_data " +
				"SET apii.user_session_data.logged_in = false " +
				"WHERE apii.user_session_data.session_id = '" + sessionId + "'");
		c.commit();
		c.close();
	}

	public static final void tieSession(HttpSession session, int userId)
			throws SQLException {
		if (session == null) {
			throw new IllegalArgumentException();
		}
		String sessionId = session.getId();
		Connection c = ServerThings.getThings().getConnection();
		Statement s = c.createStatement();

		// remove all sessions data rows with this user
		s.executeUpdate("DELETE FROM apii.user_session_data " +
				"WHERE apii.user_session_data.user_id = '" + userId + "'");

		// add this session to session list
		ResultSet sessionDataRS = s
				.executeQuery("SELECT apii.user_session_data.session_id, apii.user_session_data.user_id "
						+ "FROM apii.user_session_data "
						+ "WHERE apii.user_session_data.session_id = '"
						+ sessionId + "'");
		if (sessionDataRS.next()) {
			// user already has session
			s.executeUpdate("UPDATE apii.user_session_data "
					+ "SET apii.user_session_data.session_id = '"
					+ session.getId() + "', apii.user_session_data.user_id = '"
					+ userId + "', "
					+ "apii.user_session_data.time = '2011-11-17 17:25:27', "
					+ "apii.user_session_data.logged_in = true");
		} else {
			// tie the user to session
			s.executeUpdate("INSERT INTO apii.user_session_data VALUES " + "('"
					+ session.getId() + "', '" + userId + "', "
					+ "true, '2011-11-17 17:25:27')");
		}
		c.commit();
		c.close();
	}

	public static final UserRequesterData extractRequesterData(
			HttpSession session) throws SQLException {
		Connection c = ServerThings.getThings().getConnection();
		UserRequesterData urd = extractRequesterData(c, session);
		c.close();
		return urd;
	}

	public static final UserRequesterData extractRequesterData(Connection c,
			HttpSession session) throws SQLException {

		if (session != null) {
			String sessionId = session.getId();
			// TODO: prepared statement
			Statement s = c.createStatement();
			// check if this sessionId is in the db
			ResultSet sessionRS = s
					.executeQuery("SELECT apii.user_session_data.user_id, apii.user_session_data.logged_in "
							+ "FROM apii.user_session_data "
							+ "WHERE apii.user_session_data.session_id = '"
							+ sessionId + "'");
			if (sessionRS.next()) {
				int userId = sessionRS.getInt(1);
				boolean logged = sessionRS.getBoolean(2);
				ResultSet userRS = s
						.executeQuery("SELECT apii.users.name, apii.users.surname, apii.users.patronimic, "
								+ "apii.users.role, apii.users.password "
								+ "FROM apii.users "
								+ "WHERE apii.users.user_id = '" + userId + "'");
				if (!userRS.next()) {
					throw new Error();
				}
				
				String name = userRS.getString(1);
				String surname = userRS.getString(2);
				String patronimic = userRS.getString(3);
				int role = userRS.getInt(4);
				String pass = userRS.getString(5);
				String groupName = null;
				if (role == UserRequesterData.ROLE_STUD) {
					ResultSet groupNameRS = s.executeQuery(
							"SELECT apii.groups.name " +
							"FROM apii.groups, apii.students " +
							"WHERE apii.groups.group_id = apii.students.group_id " +
							"AND apii.students.student_id = '" + userId + "'");
					if (!groupNameRS.next()) {
						throw new Error();
					}
					groupName = groupNameRS.getString(1);
				} else if (role == UserRequesterData.ROLE_PROF) {
					groupName = null;
				} else {
					throw new Error();
				}

				return new UserRequesterData(sessionId, name,
						surname, patronimic, logged,
						role, userId, pass, groupName);
			} else {
				// we haven't the session in db: no info
				return new UserRequesterData(sessionId, null, null, null,
						false, UserRequesterData.UNKNOWN_ROLE,
						UserRequesterData.UNKNOWN_ID, null, null);
			}
		} else {
			return new UserRequesterData(null, null, null, null, false,
					UserRequesterData.UNKNOWN_ROLE,
					UserRequesterData.UNKNOWN_ID, null, null);
		}
	}

	public static final void redirectToUrl(HttpServletResponse response,
			String url) {
		String redirectLocation = ServletUtils.PREFIX + url;
		response.setContentType("text/plain");
		response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
		response.setHeader("Location", redirectLocation);
	}

	public static final void generateLoginForm(PrintWriter pw,
			String loginPrompt, String passwordPrompt, boolean incorrectInfo) {
		if (loginPrompt == null) {
			loginPrompt = "";
		}
		if (passwordPrompt == null) {
			passwordPrompt = "";
		}
		pw.println("<!DOCTYPE HTML PUBLIC \"-//W3C/DTD HTML 4.0 Transitional//EN\">");
		pw.println("<html>");
		pw.println("<title> APPII Login Page </title>");
		pw.println("<body>");
		pw.println("<center>");
		pw.println("<BR>");
		pw.println("<BR>");
		pw.println("<BR>");
		pw.println("<BR>");
		pw.println("<BR>");
		pw.println("<BR>");
		pw.println("<BR>");
		pw.println("<BR>");
		pw.println("<h2> Welcome into APII!</h2>");
		pw.println("<FORM METHOD=POST ACTION=\"login\">");
		pw.println("<p>");
		pw.println("<font size=\"2\"> <strong> Enter user ID and password: </strong></font>");
		pw.println("<BR>");
		pw.println("<strong> User ID</strong> <input type=\"text\" size=\"20\" value = \""
				+ loginPrompt + "\"name=\"" + LOGIN_NAME + "\">");
		pw.println("<strong> Password </strong>  <input type=\"password\" size=\"20\" value = \""
				+ passwordPrompt + "\"name=\"" + PASSWORD_NAME + "\">");
		pw.println("<BR>");
		pw.println("<BR>");
		pw.println("<font size=\"2\">  <strong> And then click this button: </strong></font>");
		pw.println("<input type=\"submit\" value=\"Login\">");
		pw.println("</p>");
		if (incorrectInfo) {
			pw.println("<font size=\"2\" color=\"red\" face=\"Arial\">You have entered incorrect data</font>");
		}
		pw.println("</center>");
		pw.println("</form>");
		pw.println("</body>");
		pw.println("</html>");
	}

	public static final void redirectToIllegalPage(HttpServletResponse response) {
		String redirectLocation = ServletUtils.PREFIX + "/illegal";
		response.setContentType("text/plain");
		response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
		response.setHeader("Location", redirectLocation);
	}

	public static final void redirectToErrorPage(HttpServletResponse response,
			String msg) {
		try {
			// String redirectLocation = ServletUtils.PREFIX + "/error";
			// response.setContentType("text/plain");
			// response.setStatus(response.SC_MOVED_TEMPORARILY);
			// response.setHeader("Location", redirectLocation);
			PrintWriter pw = response.getWriter();
			pw.print("ERROR: " + (msg == null ? "" : msg));
		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}
	
	public static final String getLabURLElement(int labId) {
		return "lab" + labId;
	}
	
	public static final int getLabId(String labURLElement) {
		if (!labURLElement.matches("lab\\d+")) {
			return BAD_LAB_URL_ELEMENT;
		} else {
			return Integer.parseInt(labURLElement.substring(3));
		}
	}
	
	public static final String getStudURLElement(int studId) {
		return "stud" + studId;
	}
	
	public static final int getStudId(String groupURLElement) {
		if (!groupURLElement.matches("stud\\d+")) {
			return BAD_GROUP_URL_ELEMENT;
		} else {
			return Integer.parseInt(groupURLElement.substring(4));
		}
	}
	
	public static final String getGroupURLElement(int groupId) {
		return "group" + groupId;
	}
	
	public static final int getGroupId(String groupURLElement) {
		if (!groupURLElement.matches("group\\d+")) {
			return BAD_GROUP_URL_ELEMENT;
		} else {
			return Integer.parseInt(groupURLElement.substring(5));
		}
	}
	
	public static final String getCodeURLElement(int disciplineId) {
		return "code" + disciplineId;
	}
	
	public static final int getCodeId(String disciplineURLElement) {
		if (!disciplineURLElement.matches("code\\d+")) {
			return BAD_DISCIPLINE_URL_ELEMENT;
		} else {
			return Integer.parseInt(disciplineURLElement.substring(4));
		}
	}
	
	public static final String getDisciplineURLElement(int disciplineId) {
		return "subj" + disciplineId;
	}
	
	public static final int getDisciplineId(String disciplineURLElement) {
		if (!disciplineURLElement.matches("subj\\d+")) {
			return BAD_DISCIPLINE_URL_ELEMENT;
		} else {
			return Integer.parseInt(disciplineURLElement.substring(4));
		}
	}
}
